package com.cencat.user.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 角色类型枚举
 * @author cencat
 * @since 2024-01-01
 */
@Getter
@AllArgsConstructor
public enum RoleType {

    /**
     * 系统角色
     */
    SYSTEM("SYSTEM", "系统角色", "系统内置角色，具有系统级权限", 1),

    /**
     * 管理员角色
     */
    ADMIN("ADMIN", "管理员角色", "管理员角色，具有管理权限", 2),

    /**
     * 业务角色
     */
    BUSINESS("BUSINESS", "业务角色", "业务相关角色，具有业务操作权限", 3),

    /**
     * 普通角色
     */
    NORMAL("NORMAL", "普通角色", "普通用户角色，具有基础权限", 4),

    /**
     * 访客角色
     */
    GUEST("GUEST", "访客角色", "访客角色，具有只读权限", 5),

    /**
     * 自定义角色
     */
    CUSTOM("CUSTOM", "自定义角色", "用户自定义角色，权限可配置", 6),

    /**
     * 临时角色
     */
    TEMPORARY("TEMPORARY", "临时角色", "临时角色，具有时效性", 7),

    /**
     * 特殊角色
     */
    SPECIAL("SPECIAL", "特殊角色", "特殊用途角色，权限特殊配置", 8);

    /**
     * 角色类型代码
     */
    private final String code;

    /**
     * 角色类型名称
     */
    private final String name;

    /**
     * 角色类型描述
     */
    private final String description;

    /**
     * 权限级别（数值越小权限越高）
     */
    private final Integer level;

    /**
     * 根据代码获取枚举
     * @param code 角色类型代码
     * @return 角色类型枚举
     */
    public static RoleType fromCode(String code) {
        if (code == null || code.trim().isEmpty()) {
            return null;
        }
        
        for (RoleType type : RoleType.values()) {
            if (type.getCode().equalsIgnoreCase(code.trim())) {
                return type;
            }
        }
        
        throw new IllegalArgumentException("未知的角色类型代码: " + code);
    }

    /**
     * 根据名称获取枚举
     * @param name 角色类型名称
     * @return 角色类型枚举
     */
    public static RoleType fromName(String name) {
        if (name == null || name.trim().isEmpty()) {
            return null;
        }
        
        for (RoleType type : RoleType.values()) {
            if (type.getName().equals(name.trim())) {
                return type;
            }
        }
        
        throw new IllegalArgumentException("未知的角色类型名称: " + name);
    }

    /**
     * 根据权限级别获取枚举
     * @param level 权限级别
     * @return 角色类型枚举
     */
    public static RoleType fromLevel(Integer level) {
        if (level == null) {
            return null;
        }
        
        for (RoleType type : RoleType.values()) {
            if (type.getLevel().equals(level)) {
                return type;
            }
        }
        
        throw new IllegalArgumentException("未知的权限级别: " + level);
    }

    /**
     * 检查代码是否有效
     * @param code 角色类型代码
     * @return 是否有效
     */
    public static boolean isValid(String code) {
        try {
            return fromCode(code) != null;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    /**
     * 检查名称是否有效
     * @param name 角色类型名称
     * @return 是否有效
     */
    public static boolean isValidName(String name) {
        try {
            return fromName(name) != null;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    /**
     * 检查权限级别是否有效
     * @param level 权限级别
     * @return 是否有效
     */
    public static boolean isValidLevel(Integer level) {
        try {
            return fromLevel(level) != null;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    /**
     * 获取所有角色类型代码
     * @return 角色类型代码数组
     */
    public static String[] getAllCodes() {
        RoleType[] types = RoleType.values();
        String[] codes = new String[types.length];
        for (int i = 0; i < types.length; i++) {
            codes[i] = types[i].getCode();
        }
        return codes;
    }

    /**
     * 获取所有角色类型名称
     * @return 角色类型名称数组
     */
    public static String[] getAllNames() {
        RoleType[] types = RoleType.values();
        String[] names = new String[types.length];
        for (int i = 0; i < types.length; i++) {
            names[i] = types[i].getName();
        }
        return names;
    }

    /**
     * 获取所有权限级别
     * @return 权限级别数组
     */
    public static Integer[] getAllLevels() {
        RoleType[] types = RoleType.values();
        Integer[] levels = new Integer[types.length];
        for (int i = 0; i < types.length; i++) {
            levels[i] = types[i].getLevel();
        }
        return levels;
    }

    /**
     * 获取系统级角色类型
     * @return 系统级角色类型数组
     */
    public static RoleType[] getSystemTypes() {
        return new RoleType[]{SYSTEM, ADMIN};
    }

    /**
     * 获取业务级角色类型
     * @return 业务级角色类型数组
     */
    public static RoleType[] getBusinessTypes() {
        return new RoleType[]{BUSINESS, NORMAL, CUSTOM};
    }

    /**
     * 获取访客级角色类型
     * @return 访客级角色类型数组
     */
    public static RoleType[] getGuestTypes() {
        return new RoleType[]{GUEST};
    }

    /**
     * 获取特殊角色类型
     * @return 特殊角色类型数组
     */
    public static RoleType[] getSpecialTypes() {
        return new RoleType[]{TEMPORARY, SPECIAL};
    }

    /**
     * 获取可配置角色类型（用户可以创建和修改的）
     * @return 可配置角色类型数组
     */
    public static RoleType[] getConfigurableTypes() {
        return new RoleType[]{BUSINESS, NORMAL, CUSTOM, TEMPORARY, SPECIAL};
    }

    /**
     * 获取不可配置角色类型（系统内置，用户不能修改的）
     * @return 不可配置角色类型数组
     */
    public static RoleType[] getNonConfigurableTypes() {
        return new RoleType[]{SYSTEM, ADMIN, GUEST};
    }

    /**
     * 按权限级别排序获取所有角色类型
     * @return 按权限级别排序的角色类型数组
     */
    public static RoleType[] getAllTypesByLevel() {
        RoleType[] types = RoleType.values();
        java.util.Arrays.sort(types, (a, b) -> a.getLevel().compareTo(b.getLevel()));
        return types;
    }

    /**
     * 获取高于指定级别的角色类型
     * @param level 权限级别
     * @return 高于指定级别的角色类型数组
     */
    public static RoleType[] getTypesAboveLevel(Integer level) {
        if (level == null) {
            return new RoleType[0];
        }
        
        return java.util.Arrays.stream(RoleType.values())
                .filter(type -> type.getLevel() < level)
                .toArray(RoleType[]::new);
    }

    /**
     * 获取低于指定级别的角色类型
     * @param level 权限级别
     * @return 低于指定级别的角色类型数组
     */
    public static RoleType[] getTypesBelowLevel(Integer level) {
        if (level == null) {
            return new RoleType[0];
        }
        
        return java.util.Arrays.stream(RoleType.values())
                .filter(type -> type.getLevel() > level)
                .toArray(RoleType[]::new);
    }

    /**
     * 获取指定级别范围内的角色类型
     * @param minLevel 最小级别（包含）
     * @param maxLevel 最大级别（包含）
     * @return 指定级别范围内的角色类型数组
     */
    public static RoleType[] getTypesInLevelRange(Integer minLevel, Integer maxLevel) {
        if (minLevel == null || maxLevel == null || minLevel > maxLevel) {
            return new RoleType[0];
        }
        
        return java.util.Arrays.stream(RoleType.values())
                .filter(type -> type.getLevel() >= minLevel && type.getLevel() <= maxLevel)
                .toArray(RoleType[]::new);
    }

    /**
     * 是否为系统角色
     * @return 是否系统角色
     */
    public boolean isSystem() {
        return this == SYSTEM;
    }

    /**
     * 是否为管理员角色
     * @return 是否管理员角色
     */
    public boolean isAdmin() {
        return this == ADMIN;
    }

    /**
     * 是否为业务角色
     * @return 是否业务角色
     */
    public boolean isBusiness() {
        return this == BUSINESS;
    }

    /**
     * 是否为普通角色
     * @return 是否普通角色
     */
    public boolean isNormal() {
        return this == NORMAL;
    }

    /**
     * 是否为访客角色
     * @return 是否访客角色
     */
    public boolean isGuest() {
        return this == GUEST;
    }

    /**
     * 是否为自定义角色
     * @return 是否自定义角色
     */
    public boolean isCustom() {
        return this == CUSTOM;
    }

    /**
     * 是否为临时角色
     * @return 是否临时角色
     */
    public boolean isTemporary() {
        return this == TEMPORARY;
    }

    /**
     * 是否为特殊角色
     * @return 是否特殊角色
     */
    public boolean isSpecial() {
        return this == SPECIAL;
    }

    /**
     * 是否为系统级角色（系统或管理员）
     * @return 是否系统级角色
     */
    public boolean isSystemLevel() {
        return this == SYSTEM || this == ADMIN;
    }

    /**
     * 是否为业务级角色
     * @return 是否业务级角色
     */
    public boolean isBusinessLevel() {
        return this == BUSINESS || this == NORMAL || this == CUSTOM;
    }

    /**
     * 是否为访客级角色
     * @return 是否访客级角色
     */
    public boolean isGuestLevel() {
        return this == GUEST;
    }

    /**
     * 是否为特殊级角色
     * @return 是否特殊级角色
     */
    public boolean isSpecialLevel() {
        return this == TEMPORARY || this == SPECIAL;
    }

    /**
     * 是否可配置（用户可以创建和修改）
     * @return 是否可配置
     */
    public boolean isConfigurable() {
        return this != SYSTEM && this != ADMIN && this != GUEST;
    }

    /**
     * 是否不可配置（系统内置）
     * @return 是否不可配置
     */
    public boolean isNonConfigurable() {
        return !isConfigurable();
    }

    /**
     * 是否有时效性
     * @return 是否有时效性
     */
    public boolean hasTimeLimit() {
        return this == TEMPORARY;
    }

    /**
     * 是否权限高于指定角色类型
     * @param other 其他角色类型
     * @return 是否权限更高
     */
    public boolean hasHigherLevelThan(RoleType other) {
        if (other == null) {
            return true;
        }
        return this.level < other.level;
    }

    /**
     * 是否权限低于指定角色类型
     * @param other 其他角色类型
     * @return 是否权限更低
     */
    public boolean hasLowerLevelThan(RoleType other) {
        if (other == null) {
            return false;
        }
        return this.level > other.level;
    }

    /**
     * 是否权限等于指定角色类型
     * @param other 其他角色类型
     * @return 是否权限相等
     */
    public boolean hasEqualLevelWith(RoleType other) {
        if (other == null) {
            return false;
        }
        return this.level.equals(other.level);
    }

    /**
     * 是否可以管理指定角色类型
     * @param other 其他角色类型
     * @return 是否可以管理
     */
    public boolean canManage(RoleType other) {
        if (other == null) {
            return false;
        }
        
        // 系统角色可以管理所有角色
        if (this == SYSTEM) {
            return true;
        }
        
        // 管理员角色可以管理除系统角色外的所有角色
        if (this == ADMIN) {
            return other != SYSTEM;
        }
        
        // 其他角色只能管理权限级别低于自己的角色
        return hasHigherLevelThan(other);
    }

    /**
     * 是否可以被指定角色类型管理
     * @param other 其他角色类型
     * @return 是否可以被管理
     */
    public boolean canBeManagedBy(RoleType other) {
        if (other == null) {
            return false;
        }
        return other.canManage(this);
    }

    /**
     * 获取可管理的角色类型列表
     * @return 可管理的角色类型数组
     */
    public RoleType[] getManageableTypes() {
        return java.util.Arrays.stream(RoleType.values())
                .filter(this::canManage)
                .toArray(RoleType[]::new);
    }

    /**
     * 获取可以管理当前角色的角色类型列表
     * @return 可以管理当前角色的角色类型数组
     */
    public RoleType[] getManagerTypes() {
        return java.util.Arrays.stream(RoleType.values())
                .filter(type -> type.canManage(this))
                .toArray(RoleType[]::new);
    }

    /**
     * 获取角色类型颜色（用于前端显示）
     * @return 颜色代码
     */
    public String getColor() {
        switch (this) {
            case SYSTEM:
                return "#722ed1"; // 紫色
            case ADMIN:
                return "#f5222d"; // 红色
            case BUSINESS:
                return "#1890ff"; // 蓝色
            case NORMAL:
                return "#52c41a"; // 绿色
            case GUEST:
                return "#8c8c8c"; // 灰色
            case CUSTOM:
                return "#fa8c16"; // 橙色
            case TEMPORARY:
                return "#faad14"; // 黄色
            case SPECIAL:
                return "#eb2f96"; // 粉色
            default:
                return "#d9d9d9"; // 默认灰色
        }
    }

    /**
     * 获取角色类型图标（用于前端显示）
     * @return 图标名称
     */
    public String getIcon() {
        switch (this) {
            case SYSTEM:
                return "setting";
            case ADMIN:
                return "crown";
            case BUSINESS:
                return "shop";
            case NORMAL:
                return "user";
            case GUEST:
                return "eye";
            case CUSTOM:
                return "tool";
            case TEMPORARY:
                return "clock-circle";
            case SPECIAL:
                return "star";
            default:
                return "question-circle";
        }
    }

    /**
     * 获取角色类型标签类型（用于前端显示）
     * @return 标签类型
     */
    public String getTagType() {
        switch (this) {
            case SYSTEM:
                return "purple";
            case ADMIN:
                return "red";
            case BUSINESS:
                return "blue";
            case NORMAL:
                return "green";
            case GUEST:
                return "default";
            case CUSTOM:
                return "orange";
            case TEMPORARY:
                return "gold";
            case SPECIAL:
                return "magenta";
            default:
                return "default";
        }
    }

    /**
     * 获取完整显示文本
     * @return 显示文本
     */
    public String getDisplayText() {
        return this.name + "(" + this.code + ")";
    }

    /**
     * 获取简短显示文本
     * @return 简短显示文本
     */
    public String getShortDisplayText() {
        return this.name;
    }

    /**
     * 获取详细显示文本
     * @return 详细显示文本
     */
    public String getDetailDisplayText() {
        return this.name + "(" + this.code + ") - " + this.description + " [级别:" + this.level + "]";
    }

    /**
     * 获取级别显示文本
     * @return 级别显示文本
     */
    public String getLevelDisplayText() {
        return "L" + this.level + "-" + this.name;
    }

    @Override
    public String toString() {
        return this.code;
    }
}